package com.xing.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xing.DTO.LoginDTO;
import com.xing.DTO.SysUserDTO;
import com.xing.DTO.UserRoleSaveDTO;
import com.xing.Utils.Result;
import com.xing.config.JSONUtils;
import com.xing.config.RedisUtils;
import com.xing.dao.SysUserDao;
import com.xing.dao.SysUserRoleDao;
import com.xing.email.service.EmailService;
import com.xing.email.utils.EmailTemplate;
import com.xing.entity.SysUserEntity;
import com.xing.entity.SysUserRoleEntity;
import com.xing.myInterface.MyLogger;
import com.xing.service.SysUserDetailService;
import com.xing.service.SysUserService;
import com.xing.user.User;
import com.xing.user.UserDetail;
import com.xing.utils.PageData;
import com.xing.utils.VerifyCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @version 1.0
 * @Author Xing
 * @Date 2023/12/3 22:05
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService {
    @Autowired
    private SysUserDao dao;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private SysUserDetailService userDetailService;
    @Autowired
    private SysUserRoleDao userRoleDao;
    @Autowired
    private EmailService emailService;


    public Result login(LoginDTO user) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername()).or().eq("email", user.getUsername());
        SysUserEntity entity = dao.selectOne(queryWrapper);
        if (entity != null) {
            boolean equals = new BCryptPasswordEncoder().matches(user.getPassword(), entity.getPassword());
            if (equals) {
                try {
                    UserDetail userDetail = userDetailService.getUserDetailByUsername(entity.getUsername());
                    String replace = UUID.randomUUID().toString().replace("-", "");
                    redisUtils.set("token:" + replace, JSONUtils.objToJson(userDetail.getUser()), 60 * 60 * 2, TimeUnit.MINUTES);
                    return new Result().ok(replace);
                } catch (Exception e) {
                    return new Result().err(502, "服务器异常");
                }
            }
        }
        return new Result().err(403, "账号或密码错误");
    }

    @Override
    public SysUserEntity getByUsername(String username) {
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        queryWrapper.eq("del_flag", 0);
        SysUserEntity entity = dao.selectOne(queryWrapper);
        return entity;
    }

    @Override
    public Result register(LoginDTO user) {
        String code = (String) redisUtils.get("code:" + user.getEmail());
        if (code == null) {
            return new Result().err(301, "验证码失效");
        }
        if (!code.equals(user.getCode().toUpperCase())) {
            return new Result().err(302, "验证码错误");
        }
        QueryWrapper<SysUserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("email", user.getEmail());
        SysUserEntity sysUserEntity = dao.selectOne(wrapper);
        if (sysUserEntity != null) {
            return new Result().err(501, "该账号已被注册");
        }
        SysUserEntity userEntity = new SysUserEntity();
        userEntity.setUsername("user" + UUID.randomUUID().toString().replace("-", ""));
        userEntity.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
        userEntity.setEmail(user.getEmail());
        dao.insert(userEntity);
        SysUserRoleEntity sysUserRoleEntity = new SysUserRoleEntity();
        sysUserRoleEntity.setRoleId(userRoleDao.getRoleIdByRoleName("user"));
        sysUserRoleEntity.setUserId(userEntity.getId());
        userRoleDao.insert(sysUserRoleEntity);
        QueryWrapper<SysUserEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        SysUserEntity entity = dao.selectOne(queryWrapper);
        boolean equals = new BCryptPasswordEncoder().matches(user.getPassword(), entity.getPassword());
        if (equals) {
            try {
                UserDetail userDetail = userDetailService.getUserDetailByUsername(entity.getUsername());
                String replace = UUID.randomUUID().toString().replace("-", "");
                redisUtils.set("token:" + replace, JSONUtils.objToJson(userDetail), 60 * 60 * 2, TimeUnit.MINUTES);
                return new Result().ok(replace);
            } catch (Exception e) {
                return new Result().err(500, "系统内部异常");
            }
        }
        return new Result().err(403, "账号或密码错误");
    }

    @Override
    public void getArticle(HttpServletResponse response, String key) {
        if (key == null || key.equals("")) {
            key = "xing";
        }
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            response.setContentType("image/jpg");
            String code = VerifyCodeUtils.outputVerifyImage(120, 40, outputStream, 5);
            if (!StringUtils.hasText(code)) {
                //为空处理
                log.error("注册模块：生成验证码错误");
            }
            redisUtils.set("code:" + key, code, 5, TimeUnit.MINUTES);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (!ObjectUtils.isEmpty(outputStream)) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public Result getUserInfo() {
        User principal = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        SysUserDTO sysUserDTO = dao.selectUserById(principal.getId().toString());
        sysUserDTO.setPassword("");
        return new Result().ok(sysUserDTO);
    }

    @Override
    public PageData<SysUserDTO> listByPage(Integer pageNum, Integer pageSize, String username) {
        // 封装查询条件（排除密码字段）
        LambdaQueryWrapper<SysUserEntity> userEntityLambdaQueryWrapper = Wrappers.lambdaQuery(SysUserEntity.class)
                .select(SysUserEntity.class, info -> !"password".equals(info.getColumn()))
                .eq(SysUserEntity::getDelFlag, 0);
        userEntityLambdaQueryWrapper.like(!username.isEmpty(), SysUserEntity::getUsername, username);
        Page<SysUserEntity> page = new Page<>(pageNum, pageSize);
        // 执行查询操作
        Page<SysUserEntity> userEntityPage = dao.selectPage(page, userEntityLambdaQueryWrapper);
        List<SysUserDTO> dtos = new ArrayList<>();
        for (SysUserEntity u : userEntityPage.getRecords()) {
            SysUserDTO bean = BeanUtil.toBean(u, SysUserDTO.class);
            bean.setUrl(dao.GetheadUrl(u.getHeadUrl()));
            dtos.add(bean);
        }
        // 疯转返回信息
        return new PageData<>(dtos, userEntityPage.getTotal());
    }

    @Override
    public SysUserDTO getUserById(String id) {
        return dao.selectUserById(id);
    }

    @Override
    public Boolean delUser(Long userId) {
        try {
            SysUserEntity byId = super.getById(userId);
            byId.setDelFlag(1);
            updateById(byId);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public void getArticleByEmail(String email) {
        //生产验证码
        String code = VerifyCodeUtils.generateVerifyCode(6);
        try {
            if (!StringUtils.hasText(code)) {
                //为空处理
                log.error("注册模块：生成验证码错误");
            }
            //绑定模板
            String htmlContent = new EmailTemplate().generateTemplate(0,
                    "验证码", email, "注册", code);
            //发送邮件
            emailService.sendHtmlEmail(email, "HTML 邮件", htmlContent, null);
            redisUtils.set("code:" + email, code, 30, TimeUnit.MINUTES);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean updateById(SysUserEntity entity) {
        UpdateWrapper<SysUserEntity> wrapper = new UpdateWrapper<>();
        wrapper.set(!StringUtils.isEmpty(entity.getUsername()), "username", entity.getUsername())
                .set(!StringUtils.isEmpty(entity.getPassword()), "password", entity.getPassword())
                .set(!StringUtils.isEmpty(entity.getNickname()), "nickname", entity.getNickname())
                .set(!StringUtils.isEmpty(entity.getHeadUrl()), "head_url", entity.getHeadUrl())
                .set(!StringUtils.isEmpty(entity.getGender()), "gender", entity.getGender())
                .set(!StringUtils.isEmpty(entity.getNote()), "note", entity.getNote())
                .set(!StringUtils.isEmpty(entity.getEmail()), "email", entity.getEmail())
                .set(!StringUtils.isEmpty(entity.getMobile()), "mobile", entity.getMobile())
                .set(!StringUtils.isEmpty(entity.getIdCard()), "id_card", entity.getIdCard())
                .set(!StringUtils.isEmpty(entity.getDelFlag()), "del_flag", entity.getDelFlag())
                .eq("id", entity.getId());
        return update(wrapper);
    }
}
